/**********************************************************************
 *
 *  File:
 *
 *  Created:
 *
 *  $Rev: 811 $
 *  $Id: Vec2r.hpp 811 2008-07-31 14:10:26Z karianc $
 *
 *  This file is part of the Sima library.
 *  Copyright (C) 2007 by SINTEF.  All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  ("GPL") version 2 as published by the Free Software Foundation.
 *  See the file LICENSE.GPL at the root directory of this source
 *  distribution for additional information about the GNU GPL.
 *
 *  For using Sima with software that can not be combined with the
 *  GNU GPL, please contact SINTEF for aquiring a commercial license
 *  and support.
 *
 *  SINTEF, Pb 124 Blindern, N-0314 Oslo, Norway
 *  http://www.sintef.no
 *********************************************************************/

#ifndef _SIUT_SIMD_modified_Vec2r_HPP_
#define _SIUT_SIMD_modified_Vec2r_HPP_

#include "precision.h"
#include <iostream>
#include <math.h>
#include <cmath>



namespace siut {
namespace simd {
namespace modified {


/** \brief modified: class for doing vector length 2 calculations */

class Vec2r
{

public:

  /*-----------------------------------------------------------------------*/
  /*   Vec2r                                                               */
  /*-----------------------------------------------------------------------*/

  //constructor, elements are not initialized.
  Vec2r();

  Vec2r(real x, real y);
  Vec2r(const real *pf);
  Vec2r(real tab[2]);
  Vec2r(const Vec2r &v);
  Vec2r(const real s);

  /*-----------------------------------------------------------------------*/
  /*    operators +  -  *  /                                               */
  /*-----------------------------------------------------------------------*/

  inline Vec2r operator + (const Vec2r &v) const;
  inline Vec2r operator + (const real s) const;

  inline Vec2r operator - (const Vec2r &v) const;
  inline Vec2r operator - (const real s) const;

  inline Vec2r operator * (const Vec2r &v) const;
  inline Vec2r operator * (const real s) const;

  inline Vec2r operator / (const Vec2r &v) const;
  inline Vec2r operator / (const real s) const;

  /*-----------------------------------------------------------------------*/
  /*    operators += -= *= /=                                              */
  /*-----------------------------------------------------------------------*/

  inline Vec2r & operator += (const Vec2r &v);
  inline Vec2r & operator += (const real s);

  inline Vec2r & operator -= (const Vec2r &v);
  inline Vec2r & operator -= (const real s);

  inline Vec2r & operator *= (const Vec2r &v);
  inline Vec2r & operator *= (const real s);

  inline Vec2r & operator /= (const Vec2r &v);
  inline Vec2r & operator /= (const real s);

  /*-----------------------------------------------------------------------*/
  /*    operators == != <= >= < >                                       */
  /*-----------------------------------------------------------------------*/

  inline bool operator == (const Vec2r &u) const;

  //comparison, checks if at least one corresponding element is different.
  inline bool operator != (const Vec2r &v) const;

  inline bool operator <= (const Vec2r &v) const;
  inline bool operator >= (const Vec2r &v) const;
  inline bool operator < (const Vec2r &v) const;
  inline bool operator > (const Vec2r &v) const;

  /*-----------------------------------------------------------------------*/
  /*    functions dot boolean cross abs l_inf normalize is                 */
  /*-----------------------------------------------------------------------*/

  inline real dot (const Vec2r &v) const;

  /** \brief function, checks if any elements are 0, return true if zero elements are 0. */
  inline real boolean (const Vec2r &v) const;

  inline void abs ();

  /** \brief function, returns the biggest number in absolute value. */
  inline real l_inf (const Vec2r &v) const;

  inline void normalize ();

  //sets the elements.
  inline void is (real x,  real y);

  /*-----------------------------------------------------------------------*/
  /*    functions x() y() z()  vec_[]                                         */
  /*-----------------------------------------------------------------------*/

  inline const real & x() const;
  inline real & x();
  inline const real & y() const;
  inline real & y();
  inline const real & z() const;
  inline real & z();

  //returns the ite element in vector. (obs. first element har index 0)
  inline real & operator[](int i) { return vec_[i]; }
  inline const real & operator[](int i) const { return vec_[i]; }
  inline const real* c_ptr() const { return &vec_[0]; }

  /*-----------------------------------------------------------------------*/
  /*    read  writhe                                                       */
  /*-----------------------------------------------------------------------*/

  inline void read(std::istream& is);
  inline void write(std::ostream& os) const;

  /*-----------------------------------------------------------------------*/
  /*    operators + - * / ^ with friend                                    */
  /*-----------------------------------------------------------------------*/

  inline friend Vec2r operator + (real s, const Vec2r &v);
  inline friend Vec2r operator - (real s, const Vec2r &v);
  inline friend Vec2r operator * (real s, const Vec2r &v);

  /** \brief only ^2 and ^3 (anything but 2 gives 3) */
  inline friend Vec2r operator ^ (const Vec2r &v, int i);

  /*-----------------------------------------------------------------------*/
  /*    functions dot max min sqrt length normalize with friend            */
  /*-----------------------------------------------------------------------*/

  inline friend real dot (const Vec2r &u, const Vec2r &v);

  //maximums of two vectors, ie. returns a vector with the maximums of the corresponding elements.
  inline friend Vec2r max (const Vec2r &u , const Vec2r &v);

  //minima of two vectors, ie. returns a vector with the minima of the corresponding elements.
  inline friend Vec2r min (const Vec2r &u , const Vec2r &v);

  inline friend Vec2r sqrt (const Vec2r &v);

  /** \brief function, calculates the length of a vector, ie. the square root of the sum of the element squared. */
  inline friend real length (const Vec2r &v);

  /** \brief function, calculates the length of a vector, ie. the sum of the element squared. */
  inline friend real length_2 (const Vec2r &v);

  inline friend Vec2r normalize (const Vec2r &v);

private:

  real vec_[3] ;
};

  /*-----------------------------------------------------------------------*/
  /*    IMPLEMENTATION                                                     */
  /*-----------------------------------------------------------------------*/
    /*-----------------------------------------------------------------------*/
  /*   Vec2r                                                               */
  /*-----------------------------------------------------------------------*/

  inline Vec2r::Vec2r()
  {
  }

  inline Vec2r::Vec2r( real x,  real y)
  {
    vec_[0]=x;
    vec_[1]=y;
  }

  inline Vec2r::Vec2r(const real *pf)
  {
    vec_[0]=pf[0];
    vec_[1]=pf[1];
  }

  inline Vec2r::Vec2r(real tab[2])
  {
    vec_[0]=tab[0];
    vec_[1]=tab[1];
  }

  inline Vec2r::Vec2r(const Vec2r &v)
  {
    vec_[0]=v.vec_[0];
    vec_[1]=v.vec_[1];
  }

  inline Vec2r::Vec2r(const real s)
  {
      vec_[0] = s;
      vec_[1] = s;
  }

  /*-----------------------------------------------------------------------*/
  /*    operators +  -  *  /                                               */
  /*-----------------------------------------------------------------------*/


  //operators +
  inline Vec2r Vec2r::operator + (const Vec2r &v) const
  {
    Vec2r res(*this);
    res += v;
    return res;
  }
  inline Vec2r Vec2r::operator + (const real s) const
  {
    Vec2r res(*this);
    res += s;
    return res;
  }


  //operators -
  inline Vec2r Vec2r::operator - (const Vec2r &v) const
  {
    Vec2r res(*this);
    res -= v;
    return res;
  }
  inline Vec2r Vec2r::operator - (const real s) const
  {
    Vec2r res(*this);
    res -= s;
    return res;
  }


  //operators *
  inline Vec2r Vec2r::operator * (const Vec2r &v) const
  {
    Vec2r res(*this);
    res *= v;
    return res;
  }
  inline Vec2r Vec2r::operator * (const real s) const
  {
    Vec2r res(*this);
    res *= s;
    return res;
  }


  //operators /
  Vec2r Vec2r::operator / (const Vec2r &v) const
  {
    Vec2r res(*this);
    res /= v;
    return res;
  }
  inline Vec2r Vec2r::operator / (const real s) const
  {
    Vec2r res(*this);
    res /= s;
    return res;
  }

  /*-----------------------------------------------------------------------*/
  /*    operators += -= *= /=                                              */
  /*-----------------------------------------------------------------------*/

  inline Vec2r &  Vec2r::operator += (const Vec2r &v)
  {
    vec_[0]+=v.vec_[0];
    vec_[1]+=v.vec_[1];
    return *this;
  }
  inline Vec2r & Vec2r::operator += (const real s)
  {
    vec_[0] += s;
    vec_[1] += s;
    return *this;
  }

  inline Vec2r &  Vec2r::operator -= (const Vec2r &v)
  {
    vec_[0]-=v.vec_[0];
    vec_[1]-=v.vec_[1];
    return *this;
  }
  inline Vec2r & Vec2r::operator -= (const real s)
  {
    vec_[0] -= s;
    vec_[1] -= s;
    return *this;
  }

  inline Vec2r &  Vec2r::operator *= (const Vec2r &v)
  {
    vec_[0]*=v.vec_[0];
    vec_[1]*=v.vec_[1];
    return *this;
  }
  inline Vec2r & Vec2r::operator *= (const real s)
  {
    vec_[0] *= s;
    vec_[1] *= s;
    return *this;
  }

  inline Vec2r &  Vec2r::operator /= (const Vec2r &v)
  {
    vec_[0]/=v.vec_[0];
    vec_[1]/=v.vec_[1];
    return *this;
  }
  inline Vec2r & Vec2r::operator /= (const real s)
  {
    vec_[0] /= s;
    vec_[1] /= s;
    return *this;
  }

  /*-----------------------------------------------------------------------*/
  /*    operators == != <= >= < >                                       */
  /*-----------------------------------------------------------------------*/

  //operator ==
  inline bool Vec2r::operator == (const Vec2r &u) const
  {
    real res[2];
    if (vec_[0]==u.vec_[0])
      res[0]=1.;
    else
      res[0]=0.;
    if (vec_[1]==u.vec_[1])
      res[1]=1.;
    else
      res[1]=0.;

    if (res[0] * res[1] == 0)
      {return 0;}
    else
      {return 1;}
  }


  //operator !=
  //forskjellig hvis ett tall er forskjellig
  inline bool Vec2r::operator != (const Vec2r &u) const
  {
    real res[2];
    if (vec_[0]!=u.vec_[0])
      res[0]=0.;
    else
      res[0]=1.;
    if (vec_[1]!=u.vec_[1])
      res[1]=0.;
    else
      res[1]=1.;

    if (res[0] * res[1] == 0)
      {return 1;}
    else
      {return 0;}
  }


  //operator <=
  inline bool Vec2r::operator <= (const Vec2r &u) const
  {
    real res[2];
    if (vec_[0]<=u.vec_[0])
      res[0]=1.;
    else
      res[0]=0.;
    if (vec_[1]<=u.vec_[1])
      res[1]=1.;
    else
      res[1]=0.;

    if (res[0] * res[1] == 0)
      {return 0;}
    else
      {return 1;}
  }

  //operator >=
  inline bool Vec2r::operator >= (const Vec2r &u) const
  {
    real res[2];
    if (vec_[0]>=u.vec_[0])
      res[0]=1.;
    else
      res[0]=0.;
    if (vec_[1]>=u.vec_[1])
      res[1]=1.;
    else
      res[1]=0.;

    if (res[0] * res[1] == 0)
      {return 0;}
    else
      {return 1;}
  }

  //operator <
  inline bool Vec2r::operator < (const Vec2r &u) const
  {
    real res[2];
    if (vec_[0]<u.vec_[0])
      res[0]=1.;
    else
      res[0]=0.;
    if (vec_[1]<u.vec_[1])
      res[1]=1.;
    else
      res[1]=0.;

    if (res[0] * res[1] == 0)
      {return 0;}
    else
      {return 1;}
  }


  //operator >=
  inline bool Vec2r::operator > (const Vec2r &u) const
  {
    real res[2];
    if (vec_[0]>u.vec_[0])
      res[0]=1.;
    else
      res[0]=0.;
    if (vec_[1]>u.vec_[1])
      res[1]=1.;
    else
      res[1]=0.;

    if (res[0] * res[1] == 0)
      {return 0;}
    else
      {return 1;}
  }

  /*-----------------------------------------------------------------------*/
  /*    functions dot boolean  abs l_inf normalize is                 */
  /*-----------------------------------------------------------------------*/

  //operator dot (scalar product)
  inline real Vec2r::dot (const Vec2r &v) const
  {
    return(vec_[0]*v.vec_[0] + vec_[1]*v.vec_[1]);
  }

  //operator boolean
  inline real Vec2r::boolean (const Vec2r &v) const
  {
    if (v.vec_[0] * v.vec_[1] == 0)
      {return 0;}
    else
      {return 1;}
  }

  //func abs
  inline void Vec2r::abs ()
  {
    Vec2r res(*this);
    if (res.vec_[0] < 0)
      vec_[0] = res.vec_[0] * (-1);
    if (res.vec_[1] < 0)
      vec_[1] = res.vec_[1] * (-1);
    
  }

  //func l_inf
  inline real Vec2r::l_inf (const Vec2r &v) const
  {
    real f;
    Vec2r res;

    if (v.vec_[0] < 0)
      res.vec_[0] = v.vec_[0] * (-1);
    else
      res.vec_[0] = v.vec_[0];
    if (v.vec_[1] < 0)
      res.vec_[1] = v.vec_[1] * (-1);
    else
      res.vec_[1] = v.vec_[1];

    if (res.vec_[0] >= res.vec_[1])
      f = res.vec_[0];
    else
      f = res.vec_[1];

    return f;
  }

  //func normalize
  inline void Vec2r::normalize ()
  {
    real length=std::sqrt(vec_[0]*vec_[0] + vec_[1]*vec_[1]);
    vec_[0]/=length;
    vec_[1]/=length;
  }

  //func is
  inline void Vec2r::is (real x, real y)
  {
    vec_[0] = x;
    vec_[1] = y;
  }

  /*-----------------------------------------------------------------------*/
  /*    functions x() y() z()                                              */
  /*-----------------------------------------------------------------------*/

  inline const real & Vec2r::x() const
  {    return vec_[0];  }

  inline real & Vec2r::x()
  {    return vec_[0];  }

  inline const real & Vec2r::y() const
  {    return vec_[1];  }

  inline real & Vec2r::y()
  {    return vec_[1];  }



  /*-----------------------------------------------------------------------*/
  /*    read  write                                                       */
  /*-----------------------------------------------------------------------*/

  //operators read write
  inline void Vec2r::read(std::istream& is)
  {
    is >> vec_[0] >> vec_[1];
  }

  inline void Vec2r::write(std::ostream& os) const
  {
    os << vec_[0] << " "  << vec_[1];
  }

  /*-----------------------------------------------------------------------*/
  /*    operators + - * / ^ with friend                                    */
  /*-----------------------------------------------------------------------*/

  //operators + - * / ^ with friend
  inline Vec2r operator + (real s, const Vec2r &v)
  {
    Vec2r res(s);
    res += v;
    return res;
  }

  inline Vec2r operator - (real s, const Vec2r &v)
  {
    Vec2r res(s);
    res -= v;
    return res;
  }

  inline Vec2r operator * (real s, const Vec2r &v)
  {
    Vec2r res(s);
    res *= v;
    return res;
  }

  inline Vec2r operator ^ (const Vec2r &v, int i)
  {
    Vec2r res;
    if (i == 2)
      {
        res.vec_[0]=v.vec_[0]*v.vec_[0];
        res.vec_[1]=v.vec_[1]*v.vec_[1];
      }
    else
      {
        res.vec_[0]=v.vec_[0]*v.vec_[0]*v.vec_[0];
        res.vec_[1]=v.vec_[1]*v.vec_[1]*v.vec_[1];
      }
    return res;
  }

  /*-----------------------------------------------------------------------*/
  /*    functions dot max min sqrt length normalize with friend            */
  /*-----------------------------------------------------------------------*/

  //func dot with friend

  inline real dot (const Vec2r &u, const Vec2r &v)
  {
    return(u.vec_[0]*v.vec_[0] + u.vec_[1]*v.vec_[1]);
  }

  //func max/min with friend

  inline Vec2r min (const Vec2r &u , const Vec2r &v)
  {
    Vec2r res;
    if (u.vec_[0] < v.vec_[0])
      res.vec_[0] = u.vec_[0];
    else
      res.vec_[0] = v.vec_[0];
    if (u.vec_[1] < v.vec_[1])
      res.vec_[1] = u.vec_[1];
    else
      res.vec_[1] = v.vec_[1];

    return res;
}


  inline Vec2r max (const Vec2r &u , const Vec2r &v)
  {
    Vec2r res;
    if (u.vec_[0] > v.vec_[0])
      res.vec_[0] = u.vec_[0];
    else
      res.vec_[0] = v.vec_[0];
    if (u.vec_[1] > v.vec_[1])
      res.vec_[1] = u.vec_[1];
    else
      res.vec_[1] = v.vec_[1];

    return res;
  }

  //operator sqrt
  inline Vec2r sqrt (const Vec2r &v)
  {
    Vec2r res;
    res.vec_[0] = std::sqrt(v.vec_[0]);
    res.vec_[1] = std::sqrt(v.vec_[1]);

    return res;
  }

  //operator length
  inline real length (const Vec2r &v)
  {
    return std::sqrt(v.vec_[0]*v.vec_[0]+v.vec_[1]*v.vec_[1]);
  }

  //operator length_2
  inline real length_2 (const Vec2r &v)
  {
    return (v.vec_[0]*v.vec_[0]+v.vec_[1]*v.vec_[1]);
  }

  inline Vec2r normalize (const Vec2r &v)
  {
    Vec2r res;
    real norm=(v.vec_[0]*v.vec_[0]+v.vec_[1]*v.vec_[1]);

    res = std::sqrt(norm);
    res = v/res;
    return res;
  }

  inline std::istream& operator>>(std::istream& is, Vec2r& v)
  {
    v.read(is);
    return is;
  }

  // Stream insertion for Vec2r.
  inline std::ostream& operator<<(std::ostream& os, const Vec2r& v)
  {
    v.write(os);
    return os;
  }

} //namespace modified
} //namespace simd
} //namespace siut


#endif // _SIUT_SIMD_modified_Vec2r_HPP_






